Skip to content

feat(core): allow disabling tool output truncation#28907

Open
rekram1-node wants to merge 8 commits into
devfrom
issue-13770-tool-output-docs
Open

feat(core): allow disabling tool output truncation#28907
rekram1-node wants to merge 8 commits into
devfrom
issue-13770-tool-output-docs

Conversation

@rekram1-node
Copy link
Copy Markdown
Collaborator

@rekram1-node rekram1-node commented May 22, 2026

Summary

  • allow tool_output: false to disable shared tool output truncation while keeping { max_lines, max_bytes } for custom thresholds
  • bypass truncation for generic, MCP, plugin, and streaming shell tool output when disabled
  • omit shell truncation guidance when disabled and document the public configuration
  • update the built-in customization skill to consult https://opencode.ai/config.json selectively rather than advocate disabling truncation
  • regenerate the JavaScript SDK config type

Configuration

{
  "tool_output": false
}

Or configure thresholds while truncation is enabled:

{
  "tool_output": {
    "max_lines": 200,
    "max_bytes": 8192
  }
}

Using false rather than a disabled object variant allows ordinary config merging and updates to switch between disabled truncation and configured limits without producing an invalid combined shape.

Verification

  • bun test test/config/config.test.ts test/tool/truncation.test.ts test/tool/shell.test.ts from packages/opencode
  • bun typecheck from packages/opencode
  • bun run build from packages/web
  • ./packages/sdk/js/script/build.ts
  • git diff --check

Addresses the configuration and documentation portions of #13770. Other reported behavior concerns in that issue remain separate.

Closes: #11313

@rekram1-node rekram1-node changed the title docs: document tool output truncation settings feat(core): allow disabling tool output truncation May 22, 2026
Resolve conflict in packages/opencode/src/tool/shell/prompt.ts to combine
truncationGuidance helper (which omits the truncation note when truncation
is disabled) with the configurable defaultTimeoutMs from origin/dev.

Fix typecheck in tool/truncate.ts by narrowing the tool_output union before
reading max_lines and max_bytes.
Replace the `{ enabled: boolean; maxLines: number; maxBytes: number }`
shape with `Option<{ maxLines: number; maxBytes: number }>` so the absence
of limits is represented by the type system instead of a boolean flag with
dead numeric fields.

- Truncate.limits() now returns Effect<Option<Limits>>.
- Truncate.output() short-circuits on None instead of checking .enabled.
- shell tool gates rolling buffer, disk spill, and tail truncation on
  Option.isSome(limits); behavior unchanged when truncation is enabled.
- ShellPrompt.render and helpers accept Option<Limits>; the truncation
  guidance line is omitted when None.
- Tests updated to assert Option.isSome / Option.isNone.
@rekram1-node
Copy link
Copy Markdown
Collaborator Author

/review

Comment thread packages/opencode/src/config/config.ts
@rekram1-node
Copy link
Copy Markdown
Collaborator Author

/review

Comment thread packages/opencode/src/config/config.ts Outdated
if (target.tool_output.truncate !== false && source.tool_output.truncate !== false) return merged

// Disabled truncation and custom limits are separate config modes; the later layer selects the mode.
merged.tool_output = source.tool_output
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: this replacement handles layered config loads, but the update and updateGlobal write paths later in this file still use raw mergeDeep. If an existing config has tool_output.max_lines or tool_output.max_bytes and the API writes { tool_output: { truncate: false } }, the persisted JSON can keep the old thresholds beside truncate: false, which this schema now rejects on the next load. Consider applying the same replacement semantics in those write paths when either side changes tool_output mode.

@rekram1-node
Copy link
Copy Markdown
Collaborator Author

/review

@@ -499,7 +502,7 @@ export const ShellTool = Tool.define(
sink?.write(chunk)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: when tool_output is false, this condition prevents writing to disk, but full += chunk still runs on every chunk even though full is never read in the disabled path (the final output comes from list/raw). For large outputs this keeps a second copy of the whole stream in memory. Consider skipping the full buffer entirely when limits is None so disabled truncation only stores the one buffer needed to return the untruncated output.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Long-running bash commands with large outputs cause truncation and agent retry loops

1 participant